package de.mrapp.tabswitcher.model;

import de.mrapp.tabswitcher.*;
import de.mrapp.tabswitcher.menu.OnMenuItemClickListener;
import de.mrapp.ohos_util.logging.LogLevel;
import ohos.agp.components.Component;
import de.mrapp.tabswitcher.SwipeAnimation.SwipeDirection;
import ohos.agp.components.element.Element;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;

import java.util.Collection;
import java.util.NoSuchElementException;

public interface Model extends Iterable<Tab> {
    /**
     * Defines the interface, a class, which should be notified about the model's events, must
     * implement.
     */
    interface Listener {

        /**
         * The method, which is invoked, when the log level has been changed.
         *
         * @param logLevel The log level, which has been set, as a value of the enum LogLevel. The log level
         *                 may not be null
         */
        void onLogLevelChanged(LogLevel logLevel);

        /**
         * The method, which is invoked, when the decorator has been changed.
         *
         * @param decorator The decorator, which has been set, as an instance of the class {@link
         *                  TabSwitcherDecorator}. The decorator may not be null
         */
        void onDecoratorChanged(TabSwitcherDecorator decorator);

        /**
         * The method, which is invoked, when the tab switcher has been shown.
         */
        void onSwitcherShown();

        /**
         * The method, which is invoked, when the tab switcher has been hidden.
         */
        void onSwitcherHidden();

        /**
         * The method, which is invoked, when the currently selected tab has been changed.
         *
         * @param previousIndex  The index of the previously selected tab as an {@link Integer} value or -1, if no
         *                       tab was previously selected
         * @param index          The index of the currently selected tab as an {@link Integer} value or -1, if the
         *                       tab switcher does not contain any tabs
         * @param selectedTab    The currently selected tab as an instance of the class {@link Tab} or null, if
         *                       the tab switcher does not contain any tabs
         * @param switcherHidden True, if selecting the tab caused the tab switcher to be hidden, false otherwise
         */
        void onSelectionChanged(int previousIndex, int index, Tab selectedTab,
                                boolean switcherHidden);

        /**
         * The method, which is invoked, when a tab has been added to the model.
         *
         * @param index                     The index of the tab, which has been added, as an {@link Integer} value
         * @param tab                       The tab, which has been added, as an instance of the class {@link Tab}. The tab
         *                                  may not be null
         * @param previousSelectedTabIndex  The index of the previously selected tab as an {@link Integer} value or -1, if no
         *                                  tab was selected
         * @param selectedTabIndex          The index of the currently selected tab as an {@link Integer} value or -1, if the
         *                                  tab switcher does not contain any tabs
         * @param selectionChanged          True, if the selection has changed, false otherwise
         * @param switcherVisibilityChanged True, if adding the tab caused the visibility of the tab switcher to be changed,
         *                                  false otherwise
         * @param animation                 The animation, which has been used to add the tab, as an instance of the class
         *                                  {@link Animation}. The animation may not be null
         */
        void onTabAdded(int index, Tab tab, int previousSelectedTabIndex,
                        int selectedTabIndex, boolean selectionChanged,
                        boolean switcherVisibilityChanged, Animation animation);

        /**
         * The method, which is invoked, when multiple tabs have been added to the model.
         *
         * @param index                    The index of the first tab, which has been added, as an {@link Integer} value
         * @param tabs                     An array, which contains the tabs, which have been added, as an array of the type
         *                                 {@link Tab} or an empty array, if no tabs have been added
         * @param previousSelectedTabIndex The index of the previously selected tab as an {@link Integer} value or -1, if no
         *                                 tab was selected
         * @param selectionChanged         True, if the selection has changed, false otherwise
         * @param selectedTabIndex         The index of the currently selected tab as an {@link Integer} value or -1, if the
         *                                 tab switcher does not contain any tabs
         * @param animation                The animation, which has been used to add the tabs, as an instance of the class
         *                                 {@link Animation}. The animation may not be null
         */
        void onAllTabsAdded(int index, Tab[] tabs, int previousSelectedTabIndex,
                            int selectedTabIndex, boolean selectionChanged,
                            Animation animation);

        /**
         * The method, which is invoked, when a tab has been removed from the model.
         *
         * @param index                    The index of the tab, which has been removed, as an {@link Integer} value
         * @param tab                      The tab, which has been removed, as an instance of the class {@link Tab}. The tab
         *                                 may not be null
         * @param previousSelectedTabIndex The index of the previously selected tab as an {@link Integer} value or -1, if no
         *                                 tab was selected
         * @param selectedTabIndex         The index of the currently selected tab as an {@link Integer} value or -1, if the
         *                                 tab switcher does not contain any tabs
         * @param selectionChanged         True, if the selection changed, false otherwise
         * @param animation                The animation, which has been used to remove the tab, as an instance of the class
         *                                 {@link Animation}. The animation may not be null
         */
        void onTabRemoved(int index, Tab tab, int previousSelectedTabIndex,
                          int selectedTabIndex, boolean selectionChanged,
                          Animation animation);

        /**
         * The method, which is invoked, when all tabs have been removed from the tab switcher.
         *
         * @param tabs      An array, which contains the tabs, which have been removed, as an array of the
         *                  type {@link Tab} or an empty array, if no tabs have been removed
         * @param animation The animation, which has been used to remove the tabs, as an instance of the
         *                  class {@link Animation}. The animation may not be null
         */
        void onAllTabsRemoved(Tab[] tabs, Animation animation);

        /**
         * The method, which is invoked, when the padding has been changed.
         *
         * @param left   The left padding, which has been set, in pixels as an {@link Integer} value
         * @param top    The top padding, which has been set, in pixels as an {@link Integer} value
         * @param right  The right padding, which has been set, in pixels as an {@link Integer} value
         * @param bottom The bottom padding, which has been set, in pixels as an {@link Integer} value
         */
        void onPaddingChanged(int left, int top, int right, int bottom);

        /**
         * The method, which is invoked, when it has been changed, whether the padding of the tab
         * switcher is applied to the content of its tabs, or not.
         *
         * @param applyPaddingToTabs True, if the padding of the tab switcher is applied to the content of its tabs,
         *                           false otherwise
         */
        void onApplyPaddingToTabsChanged(boolean applyPaddingToTabs);

        /**
         * The method, which is invoked, when the default icon of a tab has been changed.
         *
         * @param icon The icon, which has been set, as an instance of the class {@link Element} or
         *             null, if no icon is set
         */
        void onTabIconChanged(Element icon);

        /**
         * The method, which is invoked, when the background color of a tab has been changed.
         *
         * @param colorStateList The color state list, which has been set, as an instance of the class {@link
         *                       Color} or null, if the default color should be used
         */
        void onTabBackgroundColorChanged(Color colorStateList);

        /**
         * The method, which is invoked, when the background color of a tab's content has been
         * changed.
         *
         * @param color The color, which has been set, as an {@link Integer} value or -1, if the default
         *              color should be used
         */
        void onTabContentBackgroundColorChanged(int color);

        /**
         * The method, which is invoked, when the text color of a tab's title has been changed.
         *
         * @param colorStateList The color state list, which has been set, as an instance of the class {@link
         *                       Color} or null, if the default color should be used
         */
        void onTabTitleColorChanged(Color colorStateList);

        /**
         * The method, which is invoked, when the icon of a tab's close button has been changed.
         *
         * @param icon The icon, which has been set, as an instance of the class {@link Element} or
         *             null, if the default icon should be used
         */
        void onTabCloseButtonIconChanged(Element icon);

        /**
         * The method, which is invoked, when the color of a tab's progress bar has been changed.
         *
         * @param color The color, which has been set, as an {@link Integer} value or -1, if the default
         *              color should be used
         */
        void onTabProgressBarColorChanged(int color);

        /**
         * The method, which is invoked, when it has been changed, whether the button, which allows
         * to add a new tab, should be shown, or not.
         *
         * @param visible True, if the button, which allows to add a new tab, should be shown, false
         *                otherwise
         */
        void onAddTabButtonVisibilityChanged(boolean visible);

        /**
         * The method, which is invoked, when the color of the button, which allows to add a new
         * tab, has been changed.
         *
         * @param colorStateList The color, which has been set, as an instance of the class {@link Color}
         *                       or null, if the default color should be used
         */
        void onAddTabButtonColorChanged(Color colorStateList);

        /**
         * The method, which is invoked, when it has been changed, whether the toolbars should be
         * shown, when the tab switcher is shown, or not.
         *
         * @param visible True, if the toolbars should be shown, when the tab switcher is shown, false
         *                otherwise
         */
        void onToolbarVisibilityChanged(boolean visible);

        /**
         * The method, which is invoked, when the title of the toolbar, which is shown, when the tab
         * switcher is shown, has been changed.
         *
         * @param title The title, which has been set, as an instance of the type {@link CharSequence} or
         *              null, if no title is set
         */
        void onToolbarTitleChanged(CharSequence title);

        /**
         * The method, which is invoked, when the navigation icon of the toolbar, which is shown,
         * when the tab switcher is shown, has been changed.
         *
         * @param icon     The navigation icon, which has been set, as an instance of the class {@link
         *                 Element} or null, if no navigation icon is set
         * @param listener The listener, which should be notified, when the navigation item has been
         *                 clicked, as an instance of the type {@link Component.ClickedListener} or null, if no
         *                 listener should be notified
         */
        void onToolbarNavigationIconChanged(Element icon,
                                            Component.ClickedListener listener);

        /**
         * The method, which is invoked, when the menu of the toolbar, which is shown, when the tab
         * switcher is shown, has been inflated.
         *
         * @param resourceId The resource id of the menu, which has been inflated, as an {@link Integer}
         *                   value. The resource id must correspond to a valid menu resource
         * @param listener   The listener, which has been registered to be notified, when an item of the menu
         *                   has been clicked, as an instance of the type OnMenuItemClickListener or null, if
         *                   no listener should be notified
         */
        void onToolbarMenuInflated(int resourceId,
                                   OnMenuItemClickListener listener);

        /**
         * The method, which is invoked, when the view, which is shown, when the tab switcher is
         * empty, has been changed.
         *
         * @param view              The view, which has been set, as an instance of the class {@link Component} or null,
         *                          if no view should be shown, when the tab switcher is empty
         * @param animationDuration The duration of the fade animation, which is used to show or hide the view, in
         *                          milliseconds as a {@link Long} value. The duration must be at least 0 or -1, if
         *                          the default duration should be used
         */
        void onEmptyViewChanged(Component view, long animationDuration);

    }

    /**
     * Returns the context, which is used by the tab switcher.
     *
     * @return The context, which is used by the tab switcher, as an instance of the class {@link
     * Context}. The context may not be null
     */
    Context getContext();

    /**
     * Sets the decorator, which allows to inflate the views, which correspond to the tabs of the
     * tab switcher.
     *
     * @param decorator The decorator, which should be set, as an instance of the class {@link
     *                  TabSwitcherDecorator}. The decorator may not be null
     */
    void setDecorator(TabSwitcherDecorator decorator);

    /**
     * Returns the decorator, which allows to inflate the views, which correspond to the tabs of the
     * tab switcher.
     *
     * @return The decorator as an instance of the class {@link TabSwitcherDecorator} or null, if no
     * decorator has been set
     */
    TabSwitcherDecorator getDecorator();

    /**
     * Returns the log level, which is used for logging.
     *
     * @return The log level, which is used for logging, as a value of the enum LogLevel. The log
     * level may not be null
     */

    LogLevel getLogLevel();

    /**
     * Sets the log level, which should be used for logging.
     *
     * @param logLevel The log level, which should be set, as a value of the enum LogLevel. The log level
     *                 may not be null
     */
    void setLogLevel(LogLevel logLevel);

    /**
     * Returns, whether the tab switcher is empty, or not.
     *
     * @return True, if the tab switcher is empty, false otherwise
     */
    boolean isEmpty();

    /**
     * Returns the number of tabs, which are contained by the tab switcher.
     *
     * @return The number of tabs, which are contained by the tab switcher, as an {@link Integer}
     * value
     */
    int getCount();

    /**
     * Returns the tab at a specific index.
     *
     * @param index The index of the tab, which should be returned, as an {@link Integer} value. The
     *              index must be at least 0 and at maximum <code>getCount() - 1</code>, otherwise a
     *              {@link IndexOutOfBoundsException} will be thrown
     * @return The tab, which corresponds to the given index, as an instance of the class {@link
     * Tab}. The tab may not be null
     */

    Tab getTab(int index);

    /**
     * Returns the index of a specific tab.
     *
     * @param tab The tab, whose index should be returned, as an instance of the class {@link Tab}. The
     *            tab may not be null
     * @return The index of the given tab as an {@link Integer} value or -1, if the given tab is not
     * contained by the tab switcher
     */
    int indexOf(Tab tab);

    /**
     * Adds a new tab to the tab switcher. By default, the tab is added at the end. If the switcher
     * is currently shown, the tab is added by using an animation. By default, a {@link
     * SwipeAnimation} with direction {@link SwipeDirection#RIGHT_OR_BOTTOM} is used. If an
     * animation is currently running, the tab will be added once all previously started animations
     * have been finished.
     *
     * @param tab The tab, which should be added, as an instance of the class {@link Tab}. The tab may
     *            not be null
     */
    void addTab(Tab tab);

    /**
     * Adds a new tab to the tab switcher at a specific index. If the switcher is currently shown,
     * the tab is added by using an animation. By default, a {@link SwipeAnimation} with direction
     * {@link SwipeDirection#RIGHT_OR_BOTTOM} is used. If an animation is currently running, the tab
     * will be added once all previously started animations have been finished.
     *
     * @param tab   The tab, which should be added, as an instance of the class {@link Tab}. The tab may
     *              not be null
     * @param index The index, the tab should be added at, as an {@link Integer} value. The index must be
     *              at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *              IndexOutOfBoundsException} will be thrown
     */
    void addTab(Tab tab, int index);

    /**
     * Adds a new tab to the tab switcher at a specific index. If the switcher is currently shown,
     * the tab is added by using a specific animation. If an animation is currently running, the tab
     * will be added once all previously started animations have been finished.
     *
     * @param tab       The tab, which should be added, as an instance of the class {@link Tab}. The tab may
     *                  not be null
     * @param index     The index, the tab should be added at, as an {@link Integer} value. The index must be
     *                  at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *                  IndexOutOfBoundsException} will be thrown
     * @param animation The animation, which should be used to add the tab, as an instance of the class
     *                  {@link Animation}. The animation may not be null
     */
    void addTab(Tab tab, int index, Animation animation);

    /**
     * Adds all tabs, which are contained by a collection, to the tab switcher. By default, the tabs
     * are added at the end. If the switcher is currently shown, the tabs are added by using an
     * animation. By default, a {@link SwipeAnimation} with direction {@link
     * SwipeDirection#RIGHT_OR_BOTTOM} is used. If an animation is currently running, the tabs will
     * be added once all previously started animations have been finished.
     *
     * @param tabs A collection, which contains the tabs, which should be added, as an instance of the
     *             type {@link Collection} or an empty collection, if no tabs should be added
     */
    void addAllTabs(Collection<? extends Tab> tabs);

    /**
     * Adds all tabs, which are contained by a collection, to the tab switcher, starting at a
     * specific index. If the switcher is currently shown, the tabs are added by using an animation.
     * By default, a {@link SwipeAnimation} with direction {@link SwipeDirection#RIGHT_OR_BOTTOM} is
     * used. If an animation is currently running, the tabs will be added once all previously
     * started animations have been finished.
     *
     * @param tabs  A collection, which contains the tabs, which should be added, as an instance of the
     *              type {@link Collection} or an empty collection, if no tabs should be added
     * @param index The index, the first tab should be started at, as an {@link Integer} value. The index
     *              must be at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *              IndexOutOfBoundsException} will be thrown
     */
    void addAllTabs(Collection<? extends Tab> tabs, int index);

    /**
     * Adds all tabs, which are contained by a collection, to the tab switcher, starting at a
     * specific index. If the switcher is currently shown, the tabs are added by using a specific
     * animation. If an animation is currently running, the tabs will be added once all previously
     * started animations have been finished.
     *
     * @param tabs      A collection, which contains the tabs, which should be added, as an instance of the
     *                  type {@link Collection} or an empty collection, if no tabs should be added
     * @param index     The index, the first tab should be started at, as an {@link Integer} value. The index
     *                  must be at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *                  IndexOutOfBoundsException} will be thrown
     * @param animation The animation, which should be used to add the tabs, as an instance of the class
     *                  {@link Animation}. The animation may not be null
     */
    void addAllTabs(Collection<? extends Tab> tabs, int index,
                    Animation animation);

    /**
     * Adds all tabs, which are contained by an array, to the tab switcher. By default, the tabs are
     * added at the end. If the switcher is currently shown, the tabs are added by using an
     * animation. By default, a {@link SwipeAnimation} with direction {@link
     * SwipeDirection#RIGHT_OR_BOTTOM} is used. If an animation is currently running, the tabs will
     * be added once all previously started animations have been finished.
     *
     * @param tabs An array, which contains the tabs, which should be added, as an array of the type
     *             {@link Tab} or an empty array, if no tabs should be added
     */
    void addAllTabs(Tab[] tabs);

    /**
     * Adds all tabs, which are contained by an array, to the tab switcher, starting at a specific
     * index. If the switcher is currently shown, the tabs are added by using an animation. By
     * default, a {@link SwipeAnimation} with direction {@link SwipeDirection#RIGHT_OR_BOTTOM} is
     * used. If an animation is currently running, the tabs will be added once all previously
     * started animations have been finished.
     *
     * @param tabs  An array, which contains the tabs, which should be added, as an array of the type
     *              {@link Tab} or an empty array, if no tabs should be added
     * @param index The index, the first tab should be started at, as an {@link Integer} value. The index
     *              must be at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *              IndexOutOfBoundsException} will be thrown
     */
    void addAllTabs(Tab[] tabs, int index);

    /**
     * Adds all tabs, which are contained by an array, to the tab switcher, starting at a specific
     * index. If the switcher is currently shown, the tabs are added by using a specific animation.
     * If an animation is currently running, the tabs will be added once all previously started
     * animations have been finished.
     *
     * @param tabs      An array, which contains the tabs, which should be added, as an array of the type
     *                  {@link Tab} or an empty array, if no tabs should be added
     * @param index     The index, the first tab should be started at, as an {@link Integer} value. The index
     *                  must be at least 0 and at maximum <code>getCount()</code>, otherwise an {@link
     *                  IndexOutOfBoundsException} will be thrown
     * @param animation The animation, which should be used to add the tabs, as an instance of the class
     *                  {@link Animation}. The animation may not be null
     */
    void addAllTabs(Tab[] tabs, int index, Animation animation);

    /**
     * Removes a specific tab from the tab switcher. If the switcher is currently shown, the tab is
     * removed by using an animation. By default, a {@link SwipeAnimation} with direction {@link
     * SwipeDirection#RIGHT_OR_BOTTOM} is used. If an animation is currently running, the tab will
     * be removed once all previously started animations have been finished.
     *
     * @param tab The tab, which should be removed, as an instance of the class {@link Tab}. The tab
     *            may not be null
     */
    void removeTab(Tab tab);

    /**
     * Removes a specific tab from the tab switcher. If the switcher is currently shown, the tab is
     * removed by using a specific animation. If an animation is currently running, the tab will be
     * removed once all previously started animations have been finished.
     *
     * @param tab       The tab, which should be removed, as an instance of the class {@link Tab}. The tab
     *                  may not be null
     * @param animation The animation, which should be used to remove the tabs, as an instance of the class
     *                  {@link Animation}. The animation may not be null
     */
    void removeTab(Tab tab, Animation animation);

    /**
     * Removes all tabs from the tab switcher. If the switcher is currently shown, the tabs are
     * removed by using an animation. By default, a {@link SwipeAnimation} with direction {@link
     * SwipeDirection#RIGHT_OR_BOTTOM} is used. If an animation is currently running, the tabs will
     * be removed once all previously started animations have been finished.
     */
    void clear();

    /**
     * Removes all tabs from the tab switcher. If the switcher is currently shown, the tabs are
     * removed by using a specific animation. If an animation is currently running, the tabs will be
     * removed once all previously started animations have been finished.
     *
     * @param animation The animation, which should be used to remove the tabs, as an instance of the class
     *                  {@link Animation}. The animation may not be null
     */
    void clear(Animation animation);

    /**
     * Returns, whether the tab switcher is currently shown.
     *
     * @return True, if the tab switcher is currently shown, false otherwise
     */
    boolean isSwitcherShown();

    /**
     * Shows the tab switcher by using an animation, if it is not already shown.
     */
    void showSwitcher();

    /**
     * Hides the tab switcher by using an animation, if it is currently shown.
     */
    void hideSwitcher();

    /**
     * Toggles the visibility of the tab switcher by using an animation, i.e. if the switcher is
     * currently shown, it is hidden, otherwise it is shown.
     */
    void toggleSwitcherVisibility();

    /**
     * Returns the currently selected tab.
     *
     * @return The currently selected tab as an instance of the class {@link Tab} or null, if no tab
     * is currently selected
     */

    Tab getSelectedTab();

    /**
     * Returns the index of the currently selected tab.
     *
     * @return The index of the currently selected tab as an {@link Integer} value or -1, if no tab
     * is currently selected
     */
    int getSelectedTabIndex();

    /**
     * Selects a specific tab.
     *
     * @param tab The tab, which should be selected, as an instance of the class {@link Tab}. The tab
     *            may not be null. If the tab is not contained by the tab switcher, a {@link
     *            NoSuchElementException} will be thrown
     */
    void selectTab(Tab tab);

    /**
     * Selects the tab as a specific index.
     *
     * @param index The index of the tab, which should be selected, as an {@link Integer} value. The
     *              index must be at least 0 and at maximum <code>getCount() - 1</code>, otherwise a
     *              {@link IndexOutOfBoundsException} will be thrown
     */
    void selectTab(int index);

    /**
     * Sets the padding of the tab switcher.
     *
     * @param left   The left padding, which should be set, in pixels as an {@link Integer} value
     * @param top    The top padding, which should be set, in pixels as an {@link Integer} value
     * @param right  The right padding, which should be set, in pixels as an {@link Integer} value
     * @param bottom The bottom padding, which should be set, in pixels as an {@link Integer} value
     */
    void setPadding(int left, int top, int right, int bottom);

    /**
     * Returns the left padding of the tab switcher.
     *
     * @return The left padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingLeft();

    /**
     * Returns the top padding of the tab switcher.
     *
     * @return The top padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingTop();

    /**
     * Returns the right padding of the tab switcher.
     *
     * @return The right padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingRight();

    /**
     * Returns the bottom padding of the tab switcher.
     *
     * @return The bottom padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingBottom();

    /**
     * Returns the start padding of the tab switcher. This corresponds to the right padding, if a
     * right-to-left layout is used, or to the left padding otherwise.
     *
     * @return The start padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingStart();

    /**
     * Returns the end padding of the tab switcher. This corresponds ot the left padding, if a
     * right-to-left layout is used, or to the right padding otherwise.
     *
     * @return The end padding of the tab switcher in pixels as an {@link Integer} value
     */
    int getPaddingEnd();

    /**
     * Sets, whether the padding of the tab switcher should be applied to the content of its tabs,
     * or not. When set to <code>false</code> the padding is still taken into account for
     * positioning tabs and the tab switcher's toolbars.
     *
     * @param applyPaddingToTabs True, if the padding of the tab switcher should be applied to the content of its
     *                           tabs, false otherwise
     */
    void applyPaddingToTabs(boolean applyPaddingToTabs);

    /**
     * Returns, whether the padding of the tab switcher is applied to the content of its tabs, or
     * not.
     *
     * @return True, if the padding of the tab switcher is applied to the content of its tabs, false
     * otherwise
     */
    boolean isPaddingAppliedToTabs();

    /**
     * Returns the default icon of a tab.
     *
     * @return The default icon of a tab as an instance of the class {@link Element} or null, if no
     * icon is set
     */

    Element getTabIcon();

    /**
     * Sets the default icon of a tab.
     *
     * @param resourceId The resource id of the icon, which should be set, as an {@link Integer} value. The
     *                   resource id must correspond to a valid drawable resource
     */
    void setTabIcon(int resourceId);

    /**
     * Sets the default icon of a tab.
     *
     * @param icon The icon, which should be set, as an instance of the class {@link PixelMap} or null, if
     *             no icon should be set
     */
    void setTabIcon(PixelMap icon);

    /**
     * Returns the color state list, which is used to tint the icon of a tab.
     *
     * @return The color state list, which is used to tint the icon of a tab, as an instance of the
     * class {@link Color} or null, if the icon is not tinted
     */
    Color getTabIconTintList();

    /**
     * Sets the color, which should be used to tint the icon of a tab.
     *
     * @param color The color, which should be set, as an {@link Integer} value
     */
    void setTabIconTint(int color);

    /**
     * Sets the color state list, which should be used to tint the icon of a tab.
     *
     * @param tintList The color state list, which should be set, as an instance of the class {@link
     *                 Color} or null, if the icon should not be tinted
     */
    void setTabIconTintList(Color tintList);

    /**
     * Returns the mode, which is used to tint the icon of a tab.
     *
     * @return The mode, which is used to tint the icon of a tab, as a value of the enum {@link
     * Canvas.PorterDuffMode} or null, if the default mode is used
     */
    Canvas.PorterDuffMode getTabIconTintMode();

    /**
     * Sets the mode, which should be used to tint the icon of a tab.
     *
     * @param mode The mode, which should be set, as a value of enum {@link Canvas.PorterDuffMode} or null, if
     *             the default mode should be used
     */
    void setTabIconTintMode(Canvas.PorterDuffMode mode);

    /**
     * Returns the color state list, which is used to tint the close button of a tab.
     *
     * @return The color state list, which is used to tint the close button of a tab, as an instance
     * of the class {@link Color} or null, if the close button is not tinted
     */
    Color getTabCloseButtonIconTintList();

    /**
     * Sets the color, which should be used to tint the close button of a tab.
     *
     * @param color The color, which should be set, as an {@link Integer} value
     */
    void setTabCloseButtonIconTint(int color);

    /**
     * Sets the color state list, which should be used to tint the close button of a tab.
     *
     * @param tintList The color state list, which should be set, as an instance of the class {@link
     *                 Color} or null, if the close button should not be tinted
     */
    void setTabCloseButtonIconTintList(Color tintList);

    /**
     * Returns the mode, which is used to tint the close button of a tab.
     *
     * @return The mode, which is used to tint the close button of a tab, as a value of the enum
     * {@link Canvas.PorterDuffMode} or null, if the default mode is used
     */
    Canvas.PorterDuffMode getTabCloseButtonIconTintMode();

    /**
     * Sets the mode, which should be used to tint the close button of a tab.
     *
     * @param mode The mode, which should be set, as a value of enum {@link Canvas.PorterDuffMode} or null, if
     *             the default mode should be used
     */
    void setTabCloseButtonIconTintMode(Canvas.PorterDuffMode mode);

    /**
     * Returns the default background color of a tab.
     *
     * @return The default background color of a tab as an instance of the class {@link
     * Color} or null, if the default color is used
     */

    Color getTabBackgroundColor();

    /**
     * Sets the default background color of a tab.
     *
     * @param color The color, which should be set, as an {@link Integer} value or -1, if the default
     *              color should be used
     */
    void setTabBackgroundColor(int color);

    /**
     * Sets the default background color of a tab.
     *
     * @param colorStateList The color, which should be set, as an instance of the class {@link Color} or
     *                       null, if the default color should be used
     */
    void setTabBackgroundColor(Color colorStateList);

    int getTabTitleBackgroundColor();

    void setTabTitleBackgroundColor(int color);

    /**
     * Returns the default background color of a tab's content.
     *
     * @return The default background color of a tab's content as an {@link Integer} value
     */
    
    int getTabContentBackgroundColor();

    /**
     * Sets the default background color of a tab's content.
     *
     * @param color The color, which should be set, as an {@link Integer} value or -1, if the default
     *              color should be used
     */
    void setTabContentBackgroundColor(int color);

    /**
     * Returns the default text color of a tab's title.
     *
     * @return The default text color of a tab's title as an instance of the class {@link
     * Color} or null, if the default color is used
     */

    Color getTabTitleTextColor();

    /**
     * Sets the default text color of a tab's title.
     *
     * @param color The color, which should be set, as an {@link Integer} value or -1, if the default
     *              color should be used
     */
    void setTabTitleTextColor(int color);

    /**
     * Sets the default text color of a tab's title.
     *
     * @param colorStateList The color state list, which should be set, as an instance of the class {@link
     *                       Color} or null, if the default color should be used
     */
    void setTabTitleTextColor(Color colorStateList);

    /**
     * Returns the default icon of a tab's close button.
     *
     * @return The default icon of a tab's close button as an instance of the class {@link Element}
     * or null, if the default icon is used
     */

    Element getTabCloseButtonIcon();

    /**
     * Returns the color of a tab's progress bar.
     *
     * @return The color of a tab's progress bar as an {@link Integer} value or -1, if the default
     * color is used
     */

    int getTabProgressBarColor();

    /**
     * Sets the color of a tab's progress bar.
     *
     * @param color The color, which should be set, as an {@link Integer} value or -1, if the default
     *              color should be used
     */
    void setTabProgressBarColor(int color);

    /**
     * Sets the default icon of a tab's close button.
     *
     * @param resourceId The resource id of the icon, which should be set, as an {@link Integer} value. The
     *                   resource id must correspond to a valid drawable resource
     */
    void setTabCloseButtonIcon(int resourceId);

    /**
     * Sets the default icon of a tab's close button.
     *
     * @param icon The icon, which should be set, as an instance of the class {@link PixelMap} or null, if
     *             the default icon should be used
     */
    void setTabCloseButtonIcon(final PixelMap icon);

    /**
     * Returns, whether a button, which allows to add a new tab, is shown. When using the smartphone
     * layout, such a button is never shown. When using the tablet layout, the button is shown next
     * to the tabs.
     *
     * @return True, if a button, which allows to add a new tab, is shown, false otherwise
     */
    boolean isAddTabButtonShown();

    /**
     * Sets, whether a button, which allows to add a new tab, should be shown. This method does not
     * have any effect when using the smartphone layout. When using the tablet layout, the button is
     * shown next to the tabs.
     *
     * @param listener The listener, which should be notified, when the button has been clicked, as an
     *                 instance of the type {@link AddTabButtonListener} or null, if the button should not
     *                 be shown
     */
    void showAddTabButton(AddTabButtonListener listener);

    /**
     * Returns the color of the button, which allows to add a new tab. When using the smartphone
     * layout, such a button is never shown. When using the tablet layout, the button is shown next
     * to the tabs.
     *
     * @return The color of the button, which allows to add a new tab, as an instance of the class
     * {@link Color} or null, if the default color is used
     */

    Color getAddTabButtonColor();

    /**
     * Sets the color of the button, which allows to add a new tab. This method does not have any
     * effect when using the smartphone layout. When using the tablet layout, the button is shown
     * next to the tabs.
     *
     * @param color The color, which should be set, as an {@link Integer} value or -1, if the default
     *              color should be used
     */
    void setAddTabButtonColor(int color);

    /**
     * Sets the color of the button, which allows to add a new tab. This method does not have any
     * effect when using the smartphone layout. When using the tablet layout, the button is shown
     * next to the tabs.
     *
     * @param colorStateList The color, which should be set, as an instance of the class {@link Color} or
     *                       null, if the default color should be used
     */
    void setAddTabButtonColor(Color colorStateList);

    /**
     * Returns, whether the toolbars are shown, when the tab switcher is shown, or not. When using
     * the tablet layout, the toolbars are always shown.
     *
     * @return True, if the toolbars are shown, false otherwise
     */
    boolean areToolbarsShown();

    /**
     * Sets, whether the toolbars should be shown, when the tab switcher is shown, or not. This
     * method does not have any effect when using the tablet layout.
     *
     * @param show True, if the toolbars should be shown, false otherwise
     */
    void showToolbars(boolean show);

    /**
     * Returns the title of the toolbar, which is shown, when the tab switcher is shown. When using
     * the tablet layout, the title corresponds to the primary toolbar.
     *
     * @return The title of the toolbar, which is shown, when the tab switcher is shown, as an
     * instance of the type {@link CharSequence} or null, if no title is set
     */

    CharSequence getToolbarTitle();

    /**
     * Sets the title of the toolbar, which is shown, when the tab switcher is shown. When using the
     * tablet layout, the title is set to the primary toolbar.
     *
     * @param resourceId The resource id of the title, which should be set, as an {@link Integer} value. The
     *                   resource id must correspond to a valid string resource
     */
    void setToolbarTitle(int resourceId);

    /**
     * Sets the title of the toolbar, which is shown, when the tab switcher is shown. When using the
     * tablet layout, the title is set to the primary toolbar.
     *
     * @param title The title, which should be set, as an instance of the type {@link CharSequence} or
     *              null, if no title should be set
     */
    void setToolbarTitle(CharSequence title);

    /**
     * Returns the navigation icon of the toolbar, which is shown, when the tab switcher is shown.
     * When using the tablet layout, the icon corresponds to the primary toolbar.
     *
     * @return The icon of the toolbar, which is shown, when the tab switcher is shown, as an
     * instance of the class {@link Element} or null, if no icon is set
     */

    Element getToolbarNavigationIcon();

    /**
     * Sets the navigation icon of the toolbar, which is shown, when the tab switcher is shown. When
     * using the tablet layout, the icon is set to the primary toolbar.
     *
     * @param resourceId The resource id of the icon, which should be set, as an {@link Integer} value. The
     *                   resource id must correspond to a valid drawable resource
     * @param listener   The listener, which should be notified, when the navigation item has been clicked, as
     *                   an instance of the type {@link Component.ClickedListener} or null, if no listener should be
     *                   notified
     */
    void setToolbarNavigationIcon(int resourceId, Component.ClickedListener listener);

    /**
     * Sets the navigation icon of the toolbar, which is shown, when the tab switcher is shown. When
     * using the tablet layout, the icon is set to the primary toolbar.
     *
     * @param icon     The icon, which should be set, as an instance of the class {@link Element} or null,
     *                 if no icon should be set
     * @param listener The listener, which should be notified, when the navigation item has been clicked, as
     *                 an instance of the type {@link Component.ClickedListener} or null, if no listener should be
     *                 notified
     */
    void setToolbarNavigationIcon(Element icon, Component.ClickedListener listener);

    /**
     * Returns the color state list, which is used to tint the navigation icon of the toolbar, which
     * is shown, when the tab switcher is shown.
     *
     * @return The color state list, which is used to tint the navigation icon of the toolbar, which
     * is shown, when the tab switcher is shown, as an instance of the class {@link Color}
     * or null, if the navigation icon is not tinted
     */
    Color getToolbarNavigationIconTintList();

    /**
     * Sets the color, which should be used to tint the navigation icon of the toolbar, which is
     * shown, when the tab switcher is shown.
     *
     * @param color The color, which should be set, as an {@link Integer} value
     */
    void setToolbarNavigationIconTint(int color);

    /**
     * Sets the color state list, which should be used to tint the navigation icon of the toolbar,
     * which is shown, when the tab switcher is shown.
     *
     * @param tintList The color state list, which should be set, as an instance of the class {@link
     *                 Color} or null, if the navigation icon should not be tinted
     */
    void setToolbarNavigationIconTintList(Color tintList);

    /**
     * Returns the mode, which is used to tint the navigation icon of the toolbar, which is shown,
     * when the tab switcher is shown.
     *
     * @return The mode, which is used to tint the navigation icon of the toolbar, which is shown,
     * when the tab switcher is shown, as a value of the enum {@link Canvas.PorterDuffMode} or null, if
     * the default mode is used
     */
    Canvas.PorterDuffMode getToolbarNavigationIconTintMode();

    /**
     * Sets the mode, which should be used to tint the navigation icon of the toolbar, which is
     * shown, when the tab switcher is shown.
     *
     * @param mode The mode, which should be set, as a value of the enum {@link Canvas.PorterDuffMode} or
     *             null, if the default mode should be used
     */

    void setToolbarNavigationIconTintMode(Canvas.PorterDuffMode mode);

    /**
     * Inflates the menu of the toolbar, which is shown, when the tab switcher is shown. When using
     * the tablet layout, the menu is inflated into the secondary toolbar. If another menu has
     * already been inflated, its items will be removed.
     *
     * @param resourceId The resource id of the menu, which should be inflated, as an {@link Integer} value.
     *                   The resource id must correspond to a valid menu resource
     * @param listener   The listener, which should be notified, when an menu item has been clicked, as an
     *                   instance of the type OnMenuItemClickListener or null, if no listener should be
     *                   notified
     */
    void inflateToolbarMenu(int resourceId, OnMenuItemClickListener listener);

    /**
     * Returns the duration, which must be reached when loading the preview of a tab to use a fade
     * animation.
     *
     * @return The duration, which must be reached when loading the preview of a tab to use a fade
     * animation, in milliseconds as a {@link Long} value
     */
    long getTabPreviewFadeThreshold();

    /**
     * Sets the duration, which must be reached when loading the preview of a tab to use a fade
     * animation. Previews are only shown when using the smartphone layout.
     *
     * @param threshold The duration, which should be set, in milliseconds as a {@link Long} value. The
     *                  duration must be at least 0
     */
    void setTabPreviewFadeThreshold(long threshold);

    /**
     * Returns the duration of the fade animation, which is used to show the preview of tabs.
     *
     * @return The duration of the fade animation, which is used to show the preview of tabs, in
     * milliseconds as a {@link Long} value
     */
    long getTabPreviewFadeDuration();

    /**
     * Sets the duration of the fade animation, which is used to show the preview of tabs. Previews
     * are only shown when using the smartphone layout.
     *
     * @param duration The duration, which should be set, in milliseconds as a {@link Long} value. The
     *                 duration must be at least 0
     */
    void setTabPreviewFadeDuration(long duration);

    /**
     * Returns the view, which is shown, when the tab switcher is empty.
     *
     * @return The view, which is shown, when the tab switcher is empty, as an instance of the class
     * {@link Component} or null, if no view is shown
     */

    Component getEmptyView();

    /**
     * Sets the view, which should be shown, when the tab switcher is empty.
     *
     * @param view The view, which should be set, as an instance of the class {@link Component} or null, if
     *             no view should be shown, when the tab switcher is empty
     */
    void setEmptyView(Component view);

    /**
     * Sets the view, which should be shown, when the tab switcher is empty.
     *
     * @param view              The view, which should be set, as an instance of the class {@link Component} or null, if
     *                          no view should be shown, when the tab switcher is empty
     * @param animationDuration The duration of the fade animation, which is used to show or hide the view, in
     *                          milliseconds as a {@link Long} value. The duration must be at least 0 or -1, if the
     *                          default duration should be used
     */
    void setEmptyView(Component view, long animationDuration);

    /**
     * Sets the view, which should be shown, when the tab switcher is empty.
     *
     * @param resourceId The resource id of the view, which should be set, as an {@link Integer} value. The
     *                   resource id must correspond to a valid layout resource
     */
    void setEmptyView(int resourceId);

    /**
     * Sets the view, which should be shown, when the tab switcher is empty.
     *
     * @param resourceId        The resource id of the view, which should be set, as an {@link Integer} value. The
     *                          resource id must correspond to a valid layout resource
     * @param animationDuration The duration of the fade animation, which is used to show or hide the view, in
     *                          milliseconds as a {@link Long} value. The duration must be at least 0 or -1, if the
     *                          default duration should be used
     */
    void setEmptyView(int resourceId, long animationDuration);

    /**
     * Returns, whether saved states of tabs are cleared when the corresponding tabs are removed
     * from the tab switcher, or not.
     *
     * @return True, if saved states of tabs are cleared when the corresponding tabs are removed
     * from the tab switcher, false otherwise
     */
    boolean areSavedStatesClearedWhenRemovingTabs();

    /**
     * Sets, whether saved states of tabs should be cleared when the corresponding tabs are removed,
     * or not.
     *
     * @param clear True, if the saved states of tabs should be cleared when the corresponding tabs are
     *              removed, false otherwise
     */
    void clearSavedStatesWhenRemovingTabs(boolean clear);

    /**
     * Adds a new listener, which should be notified, when a tab is about to be closed by clicking
     * its close button.
     *
     * @param listener The listener, which should be added, as an instance of the type {@link
     *                 TabCloseListener}. The listener may not be null
     */
    void addCloseTabListener(TabCloseListener listener);

    /**
     * Removes a specific listener, which should not be notified, when a tab is about to be closed
     * by clicking its close button, anymore.
     *
     * @param listener The listener, which should be removed, as an instance of the type {@link
     *                 TabCloseListener}. The listener may not be null
     */
    void removeCloseTabListener(TabCloseListener listener);

    /**
     * Adds a new listener, which should be notified, when the preview of a tab is about to be
     * loaded. Previews are only loaded when using the smartphone layout.
     *
     * @param listener The listener, which should be added, as an instance of the type {@link
     *                 TabPreviewListener}. The listener may not be null
     */
    void addTabPreviewListener(TabPreviewListener listener);

    /**
     * Removes a specific listener, which should not be notified, when the preview of a tab is about
     * to be loaded.
     *
     * @param listener The listener, which should be removed, as an instance of the type {@link
     *                 TabPreviewListener}. The listener may not be null
     */
    void removeTabPreviewListener(TabPreviewListener listener);

}
